// lofei
//

const { ccclass, property } = cc._decorator;

/**
 * 
 */
@ccclass
export class Routes extends cc.Component {

    @property(cc.Node)
    mRouteLayer: cc.Node = null;
    @property
    mIsDebug: boolean = true;
    _allRoutesData = [];
    _graphics: cc.Graphics = null;
    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        this._graphics = this.mRouteLayer.getComponent(cc.Graphics);
        this._graphics.fillColor = cc.color(255, 255, 255, 255);

        this.loadAllRoutesData();
        if (this.mIsDebug){
            this.drawRoute();
        }
    }

    start() {
    }

    // update (dt) {}

    loadAllRoutesData() {
        this._allRoutesData = [];
        for (let i = 0; i < this.node.childrenCount; i++) {
            let anim = this.node.children[i].getComponent(cc.Animation);
            if (anim) {
                let poss = anim.defaultClip.curveData.props.position;
                this.loadRouteData(poss);
            }
        }
    }

    loadRouteData(routeData) {
        // cc.log(JSON.stringify(routeData));
        let ctrl1 = null;
        let startP = null;
        let endP = null;
        let ctrl2 = null;

        let routeCurvePath = [];
        for (let i = 0; i < routeData.length; ++i) {
            let keyFrame = routeData[i];
            if (ctrl1 != null) {
                routeCurvePath.push([startP, ctrl1, ctrl1, cc.v2(keyFrame.value[0], keyFrame.value[1])]);
            }
            startP = cc.v2(keyFrame.value[0], keyFrame.value[1]);

            for (let k = 0; k < keyFrame.motionPath.length; k++) {
                endP = cc.v2(keyFrame.motionPath[k][0], keyFrame.motionPath[k][1]);
                ctrl2 = cc.v2(keyFrame.motionPath[k][2], keyFrame.motionPath[k][3]);
                if (ctrl1 === null) {
                    ctrl1 = ctrl2;
                }
                routeCurvePath.push([startP, ctrl1, ctrl2, endP]);
                ctrl1 = cc.v2(keyFrame.motionPath[k][4], keyFrame.motionPath[k][5]);
                startP = endP;
            }
        }

        // cc.log(routeCurvePath);

        let oneRoute = [routeCurvePath[0][0]];
        for (let i = 0; i < routeCurvePath.length; i++) {
            startP = routeCurvePath[i][0];
            ctrl1 = routeCurvePath[i][1];
            ctrl2 = routeCurvePath[i][2];
            endP = routeCurvePath[i][3];

            let len = this.bezierLength(startP, ctrl1, ctrl2, endP);
            let OFFSET = 16;
            let count = Math.floor(len / OFFSET);
            let t_delta = 1 / count;
            let t = t_delta;

            for (let k = 0; k < count; k++) {
                let x = startP.x * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.x * t * (1 - t) * (1 - t) + 3 * ctrl2.x * t * t * (1 - t) + endP.x * t * t * t;
                let y = startP.y * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.y * t * (1 - t) * (1 - t) + 3 * ctrl2.y * t * t * (1 - t) + endP.y * t * t * t;
                oneRoute.push(cc.v2(x, y));
                t += t_delta;
            }
        }
        cc.log(oneRoute);
        this._allRoutesData.push(oneRoute);
    }

    drawRoute() {
        this._graphics.clear();
        for (let i = 0; i < this._allRoutesData.length; i++) {
            for (let k = 0; k < this._allRoutesData[i].length; k++) {
                let path = this._allRoutesData[i][k];
                this._graphics.moveTo(path.x - 2, path.y + 2);
                this._graphics.lineTo(path.x - 2, path.y - 2);
                this._graphics.lineTo(path.x + 2, path.y - 2);
                this._graphics.lineTo(path.x + 2, path.y + 2);
                this._graphics.close();
            }
        }
        this._graphics.fill();
    }

    bezierLength(startP, ctrl1, ctrl2, endP) {
        let prevP = startP;
        let length = 0;
        let t = 0.05;
        for (let i = 0; i < 20; i++) {
            let x = startP.x * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.x * t * (1 - t) * (1 - t) + 3 * ctrl2.x * t * t * (1 - t) + endP.x * t * t * t;
            let y = startP.y * (1 - t) * (1 - t) * (1 - t) + 3 * ctrl1.y * t * (1 - t) * (1 - t) + 3 * ctrl2.y * t * t * (1 - t) + endP.y * t * t * t;
            let nowP = cc.v2(x, y);
            let dir = nowP.sub(prevP);
            prevP = nowP;
            length += dir.mag();
            t += 0.05;
        }
        return length;
    }

    getAllRoutesData() {
        return this._allRoutesData;
    }
}
